package com.ys.data.auth.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.annotation.ApiLogDetail;
import com.common.base.BaseEnum;
import com.common.exception.BaseException;
import com.common.pojo.Result;
import com.common.util.FastJsonUtils;
import com.common.util.JWTUtils;
import com.common.util.PasswordUtil;
import com.common.util.RedisUtil;
import com.common.vo.UserLoginVo;
import com.common.vo.UserRoleVo;
import com.ys.data.auth.entity.Role;
import com.ys.data.auth.entity.RoleInfo;
import com.ys.data.auth.entity.User;
import com.ys.data.auth.mapper.RoleInfoMapper;
import com.ys.data.auth.mapper.UserMapper;
import com.ys.data.auth.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.annotation.Transient;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

/**
* @version: V1.0
* @author: szw
* @className: UserServiceImpl
* @packageName: UserServiceImpl
* @description:  用户接口实现
* @data: 2021-1-19 
**/  
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RoleInfoMapper roleInfoMapper;

    @Resource
    private RedisUtil redisUtil;

    /**
     * 新增用户和角色信息
     * @return
     */
    @Override
    @Transient
    @ApiLogDetail(detail = "鉴权服务-新增用户和角色信息",operationType=BaseEnum.INSERT)
    public Integer saveUser(UserRoleVo userRoleVo) {
        if (Objects.isNull(userRoleVo)) {
            throw new BaseException(BaseEnum.ADD_USER_INFO_IS_NULL);
        }
        //校验用户信息
        this.checkUser(userRoleVo);
        try {
            User user = new User();
            BeanUtils.copyProperties(userRoleVo, user);
            userMapper.insert(user);
            return saveAndUpdateRoleInfo(userRoleVo, user, true);
        } catch (Exception e) {
            throw new BaseException(BaseEnum.ADD_USER_ERROR, e);
        }
    }

    /**
     * 更新用户
     *
     * @param userRoleVo
     * @return
     */
    @Override
    @Transient
    @ApiLogDetail(detail = "鉴权服务-更新用户",operationType=BaseEnum.UPDATE)
    public Integer updateUser(UserRoleVo userRoleVo) {
        if (Objects.isNull(userRoleVo)) {
            throw new BaseException(BaseEnum.ADD_USER_INFO_IS_NULL);
        }
        try {
            User user = new User();
            BeanUtils.copyProperties(userRoleVo, user);
            userMapper.updateById(user);
            return saveAndUpdateRoleInfo(userRoleVo, user, false);
        } catch (Exception e) {
            throw new BaseException(BaseEnum.UPDATE_USER_INFO_ERROR);
        }
    }


    /**
     * 新增or更新角色信息表
     * flag : true 为添加操作
     * false : 为更新操作
     *
     * @param user
     * @return
     */
    @Transient
    @ApiLogDetail(detail = "鉴权服务-新增or更新角色信息表",operationType=BaseEnum.UPDATE_OR_SAVE)
    private int saveAndUpdateRoleInfo(UserRoleVo userRoleVo, User user, Boolean flag) {
        RoleInfo roleInfo = RoleInfo.builder()
                .roleId(userRoleVo.getRoleId()).userId(user.getId())
                .created(userRoleVo.getCreated()).createdDate(LocalDateTime.now())
                .build();
        try {
            if (flag) {
                return roleInfoMapper.insert(roleInfo);
            }
            return roleInfoMapper.updateById(roleInfo);
        } catch (Exception e) {
            throw new BaseException(BaseEnum.ADD_USER_ROLE_INTO_ERROR, e);
        }
    }

    /**
     * 删除用户
     *
     * @param userRoleVo
     * @return
     */
    @Transient
    @Override
    @ApiLogDetail(detail = "鉴权服务-删除用户",operationType=BaseEnum.DELETE)
    public Integer deleteUser(UserRoleVo userRoleVo) {
        if (null == userRoleVo.getId()) {
            throw new BaseException(BaseEnum.USER_ID_IS_NULL);
        }
        try {
            int result = userMapper.deleteById(userRoleVo.getId());
            if (result > 0) {
                return roleInfoMapper.deleteById(userRoleVo.getRoleId());
            }
        } catch (Exception e) {
            throw new BaseException(BaseEnum.DELETE_USER_ERROR);
        }
        return null;
    }

    /**
     * 查询用户信息
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @ApiLogDetail(detail = "鉴权服务-查询用户信息",operationType=BaseEnum.SELECT)
    public UserRoleVo findUser(Long id) throws Exception {
        if (null == id) {
            throw new BaseException(BaseEnum.USER_ID_IS_NULL);
        }
        try {
            User user = userMapper.selectById(id);
            if (Objects.isNull(user)) return null;
            UserRoleVo userRole = new UserRoleVo();
            BeanUtils.copyProperties(user, userRole);
            QueryWrapper<RoleInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", user.getId());
            RoleInfo roleInfo = roleInfoMapper.selectOne(wrapper);
            //获取到Redis中角色信息
            String redisData = redisUtil.get(BaseEnum.INIT_ROLE_REDIS_KEY.getCode());
            List<Role> redisRoleList = FastJsonUtils.getArrayJson(JSONArray.toJSONString(redisData),Role.class);
            if (CollectionUtils.isEmpty(redisRoleList)){
                return userRole;
            }
            List<Role> roleList = FastJsonUtils.getArrayJson(JSONArray.toJSONString(redisRoleList),Role.class);
            roleList.forEach(item->{
                if (item.getId().equals(roleInfo.getRoleId())){
                    userRole.setRoleCd(item.getRoleCd());
                    userRole.setId(item.getId());
                    userRole.setRemark(item.getRemark());
                    userRole.setRoleName(item.getRoleName());
                }
            });
            return userRole;
        } catch (Exception e) {
            throw new BaseException(BaseEnum.SELECT_USER_ERROR);
        }
    }

    /**
     * 用户登录接口实现
     * @param userLoginVo
     * @return
     */
    @Override
    @ApiLogDetail(detail = "鉴权服务-用户登录接口实现",operationType=BaseEnum.LOGIN)
    public Result<?> login(UserLoginVo userLoginVo) throws Exception{
        if (StringUtils.isBlank(userLoginVo.getLoginName())||StringUtils.isBlank(userLoginVo.getPassword())){
            throw new BaseException(BaseEnum.USER_LOGIN_NAME_OR_PWD_IS_NULL);
        }
        Result<User> result = new Result<>();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("login_name",userLoginVo.getLoginName())
                .and(wrapper -> wrapper.eq("password",userLoginVo.getPassword()));
        User user = userMapper.selectOne(queryWrapper);
        if(Objects.isNull(user)){
            throw new BaseException(BaseEnum.USER_LOGIN_NAME_OR_PWD_IS_ERROR);
        }
        //查询角色信息
        QueryWrapper<RoleInfo> roleInfoQueryWrapper = new QueryWrapper<>();
        roleInfoQueryWrapper.eq("user_id",user.getId());
        RoleInfo roleInfo = roleInfoMapper.selectOne(roleInfoQueryWrapper);
        String redisData = redisUtil.get(BaseEnum.INIT_ROLE_REDIS_KEY.getCode());
        List<Role> redisRoleList = FastJsonUtils.getArrayJson(JSONArray.toJSONString(redisData),Role.class);
        if (CollectionUtils.isEmpty(redisRoleList)){
            log.error("Redis获取角色信息为空");
        }
        List<Role> roleList = FastJsonUtils.getArrayJson(JSONArray.toJSONString(redisRoleList),Role.class);
        if (Objects.isNull(user)){
            throw new BaseException(BaseEnum.USER_LOGIN_NAME_OR_PWD_IS_ERROR);
        }
        AtomicReference<String> roleCd = new AtomicReference<>();
        roleList.forEach(item->{
            if(item.getId().equals(roleInfo.getId())){
                roleCd.set(item.getRoleCd());}
        });
        //生成token
        String token = JWTUtils.createJWT(user.getId(),user.getLoginName(),roleCd.get());
        return result.loginOk(token,user);
    }

    /**
     * 用户登出接口
     * @param userRoleVo
     * @return
     */
    @Override
    @ApiLogDetail(detail = "鉴权服务-用户登出接口",operationType=BaseEnum.LOGIN_OUT)
    public UserRoleVo loginOut(UserRoleVo userRoleVo) {
        return null;
    }

    /**
     * 用户信息校验
     *
     * @param userRoleVo
     * @return
     */
    private UserRoleVo checkUser(UserRoleVo userRoleVo) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("name",userRoleVo.getName()).or().eq("login_name",userRoleVo.getLoginName());
        User user = userMapper.selectOne(userQueryWrapper);
        String pwd = null;
        if (Objects.nonNull(user)) {
            throw new BaseException(BaseEnum.ADD_USER_NAME_ERROR);
        }
        //如果用户没输入密码则自动生成反之则对密码加密
        if (StringUtils.isBlank(userRoleVo.getPassword())) {
            pwd = PasswordUtil.generatePwd();
        } else {
            pwd = PasswordUtil.generatePwd(userRoleVo.getPassword());
        }
        userRoleVo.setPassword(pwd);
        return userRoleVo;
    }
}
